home *** CD-ROM | disk | FTP | other *** search
- //=--------------------------------------------------------------------------=
- // ButtonCtl.Cpp
- //=--------------------------------------------------------------------------=
- // Copyright 1995 Microsoft Corporation. All Rights Reserved.
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //=--------------------------------------------------------------------------=
- //
- #include "IPServer.H"
-
- #include "Guids.H"
- #include "ButtonCtl.H"
- #include "LocalObj.H"
- #include "Util.H"
- #include "Globals.H"
- #include "Resource.H"
-
- #include <windowsx.h>
-
- // for ASSERT and FAIL
- //
- SZTHISFILE
-
- // local private functions
- //
- short _GetShiftState(void);
-
- // these are used for events
- //
- #define LEFT_BUTTON 0x01
- #define RIGHT_BUTTON 0x02
- #define MIDDLE_BUTTON 0x04
-
-
- //=--------------------------------------------------------------------------=
- // for persistence
- //
- #define STREAMHDR_MAGIC 0x12345678
-
- typedef struct {
-
- DWORD dwMagic;
- DWORD dwVersion;
- DWORD cbSize;
-
- } STREAMHDR;
-
- WCHAR wszCaption [] = L"Caption";
-
-
- //=--------------------------------------------------------------------------=
- // all the events in this control
- //
- // TODO: add events here ...
- //
- VARTYPE rgI2I2I4I4 [] = { VT_I2, VT_I2, VT_I4, VT_I4 };
-
- typedef enum {
-
- ButtonEvent_Click = 0,
- ButtonEvent_DblClick = 1,
- ButtonEvent_MouseDown = 2,
- ButtonEvent_MouseMove = 3,
- ButtonEvent_MouseUp = 4
-
- } BUTTONEVENTS;
-
- EVENTINFO m_rgEvents [] = {
- { DISPID_CLICK, 0, NULL },
- { DISPID_DBLCLICK, 0, NULL },
- { DISPID_MOUSEDOWN, 4, rgI2I2I4I4 },
- { DISPID_MOUSEMOVE, 4, rgI2I2I4I4 },
- { DISPID_MOUSEUP, 4, rgI2I2I4I4 },
- };
-
-
- //=--------------------------------------------------------------------------=
- // array describing all of our property pages. these clsids are typically
- // in guids.h
- //
- // TODO: add any additional property page guids here ...
- //
- const GUID *rgButtonPropPages [] = {
- &CLSID_ButtonGeneralPage
- };
-
- //=--------------------------------------------------------------------------=
- // Custum Verb information
- //
- // TODO: add any custom verbs here in an array, using the VERBINFO structure.
- // then mark the controld def'n in ButtonCtl.H with
- // this verb array
- //
-
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::Create
- //=--------------------------------------------------------------------------=
- // global static function that creates an instance of the control an returns
- // an IUnknown pointer for it.
- //
- // Parameters:
- // IUnknown * - [in] controlling unknown for aggregation
- //
- // Output:
- // IUnknown * - new object.
- //
- // Notes:
- //
- IUnknown *CButtonControl::Create
- (
- IUnknown *pUnkOuter
- )
- {
- // make sure we return the private unknown so that we support aggegation
- // correctly!
- //
- CButtonControl *pNew = new CButtonControl(pUnkOuter);
- return pNew->PrivateUnknown();
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::CButtonControl
- //=--------------------------------------------------------------------------=
- // "Being born is like being kidnapped. And then sold into slavery."
- // - andy warhol (1928 - 87)
- //
- // Parameters:
- // IUnknown * - [in]
- //
- // Notes:
- //
- #pragma warning(disable:4355) // using 'this' in constructor
- CButtonControl::CButtonControl
- (
- IUnknown *pUnkOuter
- )
- : COleControl(pUnkOuter, OBJECT_TYPE_CTLBUTTON, (IDispatch *)this)
- {
- // zero out the persistent state structure.
- //
- memset(&m_state, 0, sizeof(BUTTONCTLSTATE));
-
- // TODO: initialize anything you need to here.
- //
- lstrcpy(m_state.szCaption, "Button");
- }
- #pragma warning(default:4355) // using 'this' in constructor
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::~CButtonControl
- //=--------------------------------------------------------------------------=
- // "We all labour against our own cure, for death is the cure of all diseases"
- // - Sir Thomas Browne (1605 - 82)
- //
- // Notes:
- //
- CButtonControl::~CButtonControl ()
- {
- // TODO: clean up anything here.
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl:RegisterClassData
- //=--------------------------------------------------------------------------=
- // register the window class information for your control here.
- // this information will automatically get cleaned up for you on DLL shutdown.
- //
- // Output:
- // BOOL - FALSE means fatal error.
- //
- // Notes:
- //
- BOOL CButtonControl::RegisterClassData
- (
- void
- )
- {
- WNDCLASS wndclass;
-
- // subclass a windows BUTTON control.
- //
- if (!::GetClassInfo(g_hInstance, "BUTTON", &wndclass))
- return FALSE;
-
- SUBCLASSWNDPROCOFCONTROL(OBJECT_TYPE_CTLBUTTON) = (WNDPROC)wndclass.lpfnWndProc;
- wndclass.lpfnWndProc = COleControl::ControlWindowProc;
- wndclass.lpszClassName = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLBUTTON);
-
- return RegisterClass(&wndclass);
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::BeforeCreateWindow
- //=--------------------------------------------------------------------------=
- // called just before the window is created. Great place to set up the
- // window title, etc, so that they're passed in to the call to CreateWindowEx.
- // speeds things up slightly.
- //
- // Notes:
- //
- void CButtonControl::BeforeCreateWindow
- (
- void
- )
- {
- // TODO: users should modify m_dwWindowStyle, m_dwWindowStyleEx, m_szWindowTitle
- // et al here so that the call to createwindow has as much information as
- // possible.
- // if you don't use this function, then you can probably just remove it.
- //
- m_szWindowTitle = m_state.szCaption;
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::AfterCreateWindow
- //=--------------------------------------------------------------------------=
- // we have to override this so we can set up the font from the hosts
- // ambient font.
- //
- // Notes:
- //
- void CButtonControl::AfterCreateWindow
- (
- void
- )
- {
- IFont *pFont;
- HFONT hFont;
-
- // get the HFONT for the form's ambient font.
- //
- GetAmbientFont(&pFont);
- pFont->get_hFont(&hFont);
-
- SendMessage(m_hwnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
- pFont->Release();
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::InternalQueryInterface
- //=--------------------------------------------------------------------------=
- // qi for things only we support.
- //
- // Parameters:
- // Parameters:
- // REFIID - [in] interface they want
- // void ** - [out] where they want to put the resulting object ptr.
- //
- // Output:
- // HRESULT - S_OK, E_NOINTERFACE
- //
- // Notes:
- //
- HRESULT CButtonControl::InternalQueryInterface
- (
- REFIID riid,
- void **ppvObjOut
- )
- {
- IUnknown *pUnk;
-
- *ppvObjOut = NULL;
-
- // TODO: if you want to support any additional interrfaces, then you should
- // indicate that here. never forget to call COleControl's version in the
- // case where you don't support the given interface.
- //
- if (DO_GUIDS_MATCH(riid, IID_IButton)) {
- pUnk = (IUnknown *)(IButton *)this;
- } else{
- return COleControl::InternalQueryInterface(riid, ppvObjOut);
- }
-
- pUnk->AddRef();
- *ppvObjOut = (void *)pUnk;
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::LoadTextState
- //=--------------------------------------------------------------------------=
- // load in our text state for this control.
- //
- // Parameters:
- // IPropertyBag * - [in] property bag to read from
- // IErrorLog * - [in] errorlog object to use with proeprty bag
- //
- // Output:
- // HRESULT
- //
- // Notes:
- // - NOTE: if you have a binary object, then you should pass an unknown
- // pointer to the property bag, and it will QI it for IPersistStream, and
- // get said object to do a Load()
- //
- STDMETHODIMP CButtonControl::LoadTextState
- (
- IPropertyBag *pPropertyBag,
- IErrorLog *pErrorLog
- )
- {
- VARIANT v;
-
- v.vt = VT_BSTR;
- v.bstrVal = NULL;
-
- // try to load in the property. if we can't get it, then leave
- // things at their default.
- //
- pPropertyBag->Read(wszCaption, &v, pErrorLog);
- if (v.bstrVal) {
- MAKE_ANSIPTR_FROMWIDE(psz, v.bstrVal);
- lstrcpyn(m_state.szCaption, psz, sizeof(m_state.szCaption));
- VariantClear(&v);
- }
-
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::LoadBinaryState
- //=--------------------------------------------------------------------------=
- // loads in our binary state using streams.
- //
- // Parameters:
- // IStream * - [in] stream to write to.
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP CButtonControl::LoadBinaryState
- (
- IStream *pStream
- )
- {
- STREAMHDR sh;
- HRESULT hr;
-
- // first read in the streamhdr, and make sure we like what we're getting
- //
- hr = pStream->Read(&sh, sizeof(sh), NULL);
- RETURN_ON_FAILURE(hr);
-
- // sanity check
- //
- if (sh.dwMagic != STREAMHDR_MAGIC || sh.cbSize != sizeof(m_state))
- return E_UNEXPECTED;
-
- // read in the control state information
- //
- hr = pStream->Read(&(m_state), sizeof(m_state), NULL);
- RETURN_ON_FAILURE(hr);
-
- return S_OK;
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::SaveTextState
- //=--------------------------------------------------------------------------=
- // saves out the text state for this control using a property bag.
- //
- // Parameters:
- // IPropertyBag * - [in] the property bag with which to work.
- // BOOL - [in] if TRUE, then write out ALL properties, even
- // if they're their the default value ...
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP CButtonControl::SaveTextState
- (
- IPropertyBag *pPropertyBag,
- BOOL fWriteDefaults
- )
- {
- HRESULT hr;
- VARIANT v;
-
- v.vt = VT_BSTR;
- v.bstrVal = BSTRFROMANSI(m_state.szCaption);
- RETURN_ON_NULLALLOC(v.bstrVal);
-
- // this control currently only persists out the caption property
- //
- hr = pPropertyBag->Write(wszCaption, &v);
- VariantClear(&v);
- return hr;
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::SaveBinaryState
- //=--------------------------------------------------------------------------=
- // save out the binary state for this control, using the given IStream object.
- //
- // Parameters:
- // IStream * - [in] save to which you should save.
- //
- // Output:
- // HRESULT
- //
- // Notes:
- // - it is important that you seek to the end of where you saved your
- // properties when you're done with the IStream.
- //
- STDMETHODIMP CButtonControl::SaveBinaryState
- (
- IStream *pStream
- )
- {
- STREAMHDR sh = { STREAMHDR_MAGIC, MAKELONG(1, 0), sizeof(m_state) };
- HRESULT hr;
-
- // write out the stream hdr.
- //
- hr = pStream->Write(&sh, sizeof(sh), NULL);
- RETURN_ON_FAILURE(hr);
-
- // write out he control state information
- //
- hr = pStream->Write(&m_state, sizeof(m_state), NULL);
- return hr;
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::OnDraw
- //=--------------------------------------------------------------------------=
- // "I don't very much enjoy looking at paintings in general. i know too
- // much about them. i take them apart."
- // - georgia o'keeffe (1887-1986)
- //
- // Parameters:
- // HDC - [in] HDC to draw to
- // LPCRECTL - [in] rect we're drawing to
- // LPCRECTL - [in] window extent and origin for meta-files
- // HDC - [in] HIC for target device
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- HRESULT CButtonControl::OnDraw
- (
- HDC hdcDraw,
- LPCRECTL prcBounds,
- LPCRECTL prcWBounds,
- HDC hicTargetDevice
- )
- {
- // TODO: put your drawing code here ...
- //
- return DoSuperClassPaint(hdcDraw, prcBounds);
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::WindowProc
- //=--------------------------------------------------------------------------=
- // window procedure for this control. nothing terribly exciting.
- //
- // Parameters:
- // see win32sdk on window procs.
- //
- // Notes:
- //
- LRESULT CButtonControl::WindowProc
- (
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- switch (msg) {
- case WM_LBUTTONDOWN:
- case WM_RBUTTONDOWN:
- case WM_MBUTTONDOWN:
- {
- short s = (msg == WM_LBUTTONDOWN) ? LEFT_BUTTON : ((msg == WM_RBUTTONDOWN) ? RIGHT_BUTTON : MIDDLE_BUTTON);
- FireEvent(&(m_rgEvents[ButtonEvent_MouseDown]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
- }
- break;
-
- case WM_LBUTTONDBLCLK:
- case WM_RBUTTONDBLCLK:
- case WM_MBUTTONDBLCLK:
- FireEvent(&(m_rgEvents[ButtonEvent_DblClick]));
- break;
-
- case WM_RBUTTONUP:
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- {
- short s = (msg == WM_LBUTTONUP) ? LEFT_BUTTON : ((msg == WM_RBUTTONUP) ? RIGHT_BUTTON : MIDDLE_BUTTON);
- FireEvent(&(m_rgEvents[ButtonEvent_MouseUp]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
- }
- break;
-
- case WM_MOUSEMOVE:
- {
- short s = (wParam & MK_LBUTTON) ? LEFT_BUTTON : ((wParam & MK_RBUTTON) ? RIGHT_BUTTON : ((wParam & MK_MBUTTON) ? MIDDLE_BUTTON : 0));
- FireEvent(&(m_rgEvents[ButtonEvent_MouseMove]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
- }
- break;
-
-
- case OCM_COMMAND:
- switch (LOWORD(wParam)) {
- case BN_CLICKED:
- FireEvent(&(m_rgEvents[ButtonEvent_Click]));
- break;
- }
- break;
- }
-
- // pass anything else on to the superproc.
- //
- return CallWindowProc((FARPROC)SUBCLASSWNDPROCOFCONTROL(OBJECT_TYPE_CTLBUTTON), hwnd, msg, wParam, lParam);
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::AboutBox
- //=--------------------------------------------------------------------------=
- // prints up an about box. fweeeee.
- //
- // Notes:
- //
- void CButtonControl::AboutBox
- (
- void
- )
- {
- // TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
- // they wanted a slightly more interesting About Box ... you should
- // still call ModalDialog first, however.
- //
- ModalDialog(TRUE);
- MessageBox(NULL, "This is My Control", "About Button", MB_OK | MB_TASKMODAL);
- ModalDialog(FALSE);
- }
-
- //=--------------------------------------------------------------------------=
- // CButtonControl::get_Caption [IButton]
- //=--------------------------------------------------------------------------=
- // returns current caption
- //
- // Parameters:
- // BSTR * - [out] duh
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP CButtonControl::get_Caption
- (
- BSTR *pbstrCaption
- )
- {
- CHECK_POINTER(pbstrCaption);
-
- *pbstrCaption = (*m_state.szCaption) ? BSTRFROMANSI(m_state.szCaption) : SysAllocString(L"");
-
- return (*pbstrCaption) ? S_OK : E_OUTOFMEMORY;
- }
- //=--------------------------------------------------------------------------=
- // CButtonControl::put_Caption [IButton]
- //=--------------------------------------------------------------------------=
- // sets the new caption
- //
- // Parameters:
- // BSTR - [in] duh
- //
- // Output:
- // HRESULT
- //
- // Notes:
- //
- STDMETHODIMP CButtonControl::put_Caption
- (
- BSTR bstrCaption
- )
- {
- // get an ANSI pointer, so we can stuff it in our local buffer for captions!
- //
- if (!bstrCaption) bstrCaption = L"";
- MAKE_ANSIPTR_FROMWIDE(pszCaption, bstrCaption);
-
- // if it hasn't changed, don't waste any time.
- //
- if (!lstrcmp(m_state.szCaption, pszCaption))
- return S_OK;
-
- // copy it over
- //
- lstrcpyn(m_state.szCaption, pszCaption, sizeof(m_state.szCaption));
-
- // update the window, if appropriate.
- //
- if (m_hwnd) {
- Button_SetText(m_hwnd, m_state.szCaption);
- InvalidateControl(NULL);
- }
-
- // update anybody who cares about property changes and mark ourselves
- // as dirty
- //
- PropertyChanged(DISPID_CAPTION);
- m_fDirty = TRUE;
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // _GetShiftState [standard helper!]
- //=--------------------------------------------------------------------------=
- // used by people to get shift state information
- //
- // Output:
- // short - mask of shift, ctrl and alt keys
- //
- // Notes:
- //
- short _GetShiftState
- (
- void
- )
- {
- BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
- BOOL bCtrl = (GetKeyState(VK_CONTROL) < 0);
- BOOL bAlt = (GetKeyState(VK_MENU) < 0);
-
- return (short)(bShift + (bCtrl << 1) + (bAlt << 2));
-
- }
-